/** 
Copyright (c) 2010, Sheikh Abdul Wahid Ahmed
Details @ http://extremecodeworld.codeplex.com/license
**/

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using EXtremecode.Utils;
using EXtremecode.Common;
using EXtremecode.PresentationLayer;


namespace EXtremecode.PresentationLayer
{
    /// <summary>
    /// Summary description for AWSiteMapProvder
    /// </summary>
    public class AWSiteMapProvider : SiteMapProvider
    {

        XmlDocument doc;
        private SiteMapNode rootNode;
        private string resourceClass = string.Empty;
        private bool isFiltrationIgnored = false;
        bool ignoreIsMenuItemFlag = false;
        private string rootNodeKey = string.Empty;





        public AWSiteMapProvider()
        { }

        private static string GetAttributeValue(XmlNode node, string attribute)
        {
            if (node != null && node.Attributes[attribute] != null)
            {
                return node.Attributes[attribute].Value;

            }
            else
            {
                if (attribute == "name")
                {
                    throw new Exception("node name should be defined");
                }
                return string.Empty;
            }
        }

        private SiteMapNode CreateSiteMapNode(XmlNode xmlNode)
        {
            bool isMenuItem = (GetAttributeValue(xmlNode, "isMenuItem") == "false") ? false : true;
            if (!isMenuItem && !ignoreIsMenuItemFlag)
            {
                return CreateSiteMapNode(xmlNode.ParentNode);
            }

            string name = GetAttributeValue(xmlNode, "name");
            string url = GetAttributeValue(xmlNode, "url");
            bool ignoreAuthorization = (GetAttributeValue(xmlNode, "ignoreAuthorization") == "true" &&
                    (GetAttributeValue(xmlNode, "ignoreAuthentication") == "true" ||
                        (SessionRepository.Instance.UserProfile != null &&
                         SessionRepository.Instance.UserProfile.User != null))) ? true : false;

            if (!ignoreAuthorization && !isFiltrationIgnored && rootNodeKey != name && !string.IsNullOrEmpty(url))
            //we can ignore filtration. if ...
            //url is not defined or
            //node is root node. or
            //filtration is forcefully ignored.
            //authorization is explicitly ignored.
            {
                bool isUserAuthorized =
                    (SessionRepository.Instance.UserProfile != null &&
                        SessionRepository.Instance.UserProfile.User != null) ?
                    SessionRepository.Instance.UserProfile.User.IsUserAuthorizedForModule(name) :
                    false;
                if (!isUserAuthorized)
                {
                    return null;
                }
            }

            SiteMapNode siteMapNode = new SiteMapNode(this, name, url);
            siteMapNode.Title = ResourceProvider.GetResourceString(resourceClass, "Title_" + name);
            siteMapNode.Description = ResourceProvider.GetResourceString(resourceClass, "Description_" + name);

            if (string.IsNullOrEmpty(siteMapNode.Title))
            {
                siteMapNode.Title = name;
            }

            return siteMapNode;
        }



        // Return the root node of the current site map.
        public override SiteMapNode RootNode
        {
            get
            {
                if (rootNode == null)
                {
                    //get first element.
                    XmlNode firstElement = doc.DocumentElement.FirstChild;
                    while (true)
                    {
                        if (firstElement is XmlElement
                            || firstElement == null)
                        {
                            break;
                        }
                        firstElement = firstElement.NextSibling;
                    }
                    rootNode = CreateSiteMapNode(firstElement);
                }
                return rootNode;
            }
        }


        public override SiteMapNode FindSiteMapNodeFromKey(string key)
        {
            SiteMapNode siteMapNode = null;
            XmlNodeList nodeList = XmlUtil.GetNodes(doc.DocumentElement,
                 string.Format("//x:siteMapNode[@name = '{0}']", key), string.Empty, "x");

            if (nodeList.Count > 0)
            {
                siteMapNode = CreateSiteMapNode(nodeList[0]);
            }
            return siteMapNode;
        }
        public override SiteMapNode FindSiteMapNode(string rawUrl)
        {
            SiteMapNode siteMapNode = null;
            if (string.IsNullOrEmpty(rawUrl))
            {
                return null;
            }

            string url = rawUrl;
            // rawUrl like  '/ASPNetTest/EmployeeEdit.aspx' 
            // rawUrl like  '~/EmployeeEdit.aspx'


            // take the virtual directory name away from the url e.g.   'ASPNetTest' 
            int endingIndex = rawUrl.IndexOf('/', 1);
            if (endingIndex >= 1)
            {
                url = "~" + rawUrl.Substring(endingIndex);
            }

            //now find it.
            //get query string paramenters away one by one and search again untill prameters get finished or 
            //search get successfull.
            int ampersetPosition = url.Length;
            while (true)
            {
                url = url.Substring(0, ampersetPosition);

                XmlNodeList nodeList = XmlUtil.GetNodes(doc.DocumentElement,
                    string.Format("//x:siteMapNode[@url = '{0}']", url), string.Empty, "x");

                if (nodeList.Count > 0)
                {
                    //search successfull
                    siteMapNode = CreateSiteMapNode(nodeList[0]);
                    break;
                }
                else
                {
                    ampersetPosition = url.LastIndexOf('&');

                    if (ampersetPosition < 0)
                    {
                        //no parameter more.
                        break;
                    }
                }
            }
            return siteMapNode;


        }

        public override SiteMapNodeCollection GetChildNodes(SiteMapNode node)
        {
            SiteMapNodeCollection siteMapCol = new SiteMapNodeCollection();
            XmlNodeList nodeList = XmlUtil.GetNodes(doc.DocumentElement,
                string.Format("//x:siteMapNode[@name = '{0}']", node.Key), string.Empty, "x");

            if (nodeList.Count > 0)
            {
                foreach (XmlElement element in nodeList[0].ChildNodes)
                {
                    bool isMenuItem = (GetAttributeValue(element, "isMenuItem") == "false") ? false : true;
                    if (!isMenuItem && !ignoreIsMenuItemFlag)
                    {
                        //if node is not a menu item then no need to add it into collection.
                        continue;
                    }
                    SiteMapNode siteMapNode = CreateSiteMapNode(element);
                    if (siteMapNode != null)
                    {
                        siteMapCol.Add(siteMapNode);
                    }
                }
            }
            return siteMapCol;
        }

        public override SiteMapNode GetParentNode(SiteMapNode node)
        {
            SiteMapNode siteMapParentNode = null;
            XmlNodeList nodeList = XmlUtil.GetNodes(doc.DocumentElement,
                string.Format("//x:siteMapNode[@name = '{0}']", node.Key), string.Empty, "x");

            if (nodeList.Count > 0)
            {
                if (nodeList[0].ParentNode != null && nodeList[0].ParentNode != doc.DocumentElement)
                {
                    siteMapParentNode = CreateSiteMapNode(nodeList[0].ParentNode);
                }
            }
            return siteMapParentNode;
        }

        protected override SiteMapNode GetRootNodeCore()
        {
            return RootNode;
        }

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection attributes)
        {
            doc = new XmlDocument();
            doc.Load(System.AppDomain.CurrentDomain.BaseDirectory + attributes["siteMapFile"]);
            isFiltrationIgnored = (attributes["filtrationIgnoredFlag"] != null &&
                attributes["filtrationIgnoredFlag"].Equals("true", StringComparison.CurrentCultureIgnoreCase)) ?
                true : false;

            ignoreIsMenuItemFlag = (attributes["ignoreIsMenuItemFlag"] != null &&
                 attributes["ignoreIsMenuItemFlag"].Equals("true", StringComparison.CurrentCultureIgnoreCase)) ?
                    true : false;

            resourceClass = doc.DocumentElement.Attributes["resourceClass"].Value;

            //get first element.
            XmlNode firstElement = doc.DocumentElement.FirstChild;
            while (true)
            {
                if (firstElement is XmlElement
                    || firstElement == null)
                {
                    break;
                }
                firstElement = firstElement.NextSibling;
            }

            rootNodeKey = GetAttributeValue(firstElement, "name");

            base.Initialize(name, attributes);
        }

    }
}